﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ECS.Demos.Tetris.Systems;
using EntityComponentSystem.Framework.Math;
using EntityComponentSystem.Framework;
using ECS.Demos.Tetris.Behavoirs;
using ECS.Demos.Tetris.Components;
using EntityComponentSystem.Framework.Systems;
using EntityComponentSystem.Framework.Json;
using System.Diagnostics;

namespace ECS.Demos.Tetris
{
    static class Program
    {

        public static bool IsRunning = true;

        private static List<bool> func_cleanup = new List<bool>();
        private static List<Func<float, bool>> func_list = new List<Func<float, bool>>();
        private static JsonObject jo = new JsonObject(new string[] { "position", "size" }, new object[] { 1f, 2f });

        public static JsonObject animate(this JsonObject j, float ms, string val)
        {
            return j.animate(ms, (r, o) =>
            {
                o[val] = r;
            });
        }

        public static JsonObject animate(this JsonObject j, float ms, string val)
        {
            return j.animate(ms, (r, o) =>
            {
                o[val] = r;
            });
        }

        public static JsonObject animate(this JsonObject j, float ms, Action<float, JsonObject> ease)
        {
            var tr = ms;
            func_cleanup.Add(false);
            func_list.Add((delta) =>
            {
                tr -= delta;
                if (tr < 0)
                    tr = 0;

                ease(1f - (tr / ms), j);
                return tr <= 0;
            });
            return j;
        }



        [STAThread]
        static void Main()
        {
            float start = jo["size"];
            jo.animate(1f, "position").animate(1f, (r, o) =>
            {
                o["size"] = start + r * 10;
            });

            for (var i = 0; i < 10; i++)
            {
                for (int k = func_list.Count - 1; k >= 0; k--)
                {
                    if (func_cleanup[k])
                    {
                        func_cleanup.RemoveAt(k);
                        func_list.RemoveAt(k);
                    }
                }

                for (var k = 0; k < func_list.Count; k++)
                {
                    if (func_list[k](0.1f))
                        func_cleanup[k] = true;
                }
                Console.WriteLine(jo.ToString());
            }
            Console.Read();

            var ge2 = new GameEngine();

            ge2.RegisterSystem(new ConsoleRenderSystem());
            ge2.RegisterSystem(new IntervalBehaviorSystem("interval", 0.7f));
            ge2.RegisterSystem(new InputSystem());
            ge2.RegisterSystem(new BlockConstraintSystem());

            ge2.RegisterBehavior(new DrawSpriteBehavior());
            ge2.RegisterBehavior(new DrawTextBehavior());
            ge2.RegisterBehavior(new DrawFrameBehavior());
            ge2.RegisterBehavior(new DrawBlocksBehavior());
            ge2.RegisterBehavior(new FallingBlockBehavior());
            ge2.RegisterBehavior(new BlockInputBehavior());

            //var entity = ge2.CreateEntity("entities\\test1.json");
            //entity = ge2.CreateEntity("entities\\test2.json");
            //entity = ge2.CreateEntity("entities\\frame.json");
            var shape = ge2.CreateEntity("entities\\zshape.json");
            ge2.AddBehavior(shape, "input.block");


            var blockframe = ge2.CreateEntity("entities\\frame.json");
            ge2.SetComponent(blockframe, "position", "x", 30);
            ge2.SetComponent(blockframe, "position", "y", 0);
            ge2.SetComponent(blockframe, "size", "width", 20);
            ge2.SetComponent(blockframe, "size", "height", 30);
            ge2.AddTag(blockframe, "blockframe");


            var sw = new Stopwatch();
            sw.Start();

            long lastTick = 0;
            while (IsRunning)
            {
                var nextTick = sw.ElapsedMilliseconds;
                var tickDiff = nextTick - lastTick;

                ge2.Update(tickDiff / 1000f);
                lastTick = nextTick;
                System.Threading.Thread.Sleep(0);
            }
            //Console.Read();

            sw.Stop();
            ge2.Dispose();

        }

    }

}
